package com.webchat.pgc.service.sys;

import com.webchat.common.bean.APIPageResponseBean;
import com.webchat.common.enums.RedisKeyEnum;
import com.webchat.common.exception.BusinessException;
import com.webchat.common.service.RedisService;
import com.webchat.common.util.JsonUtil;
import com.webchat.domain.vo.request.sys.SysDataDictionaryRequestVO;
import com.webchat.domain.vo.response.mall.MallShopBaseVO;
import com.webchat.domain.vo.response.sys.SysDataDictionaryBaseVO;
import com.webchat.domain.vo.response.sys.SysDataDictionaryResponseVO;
import com.webchat.pgc.repository.dao.sys.ISysDataDictionaryCategoryDAO;
import com.webchat.pgc.repository.dao.sys.ISysDataDictionaryDAO;
import com.webchat.pgc.repository.dao.sys.ISysDataDictionaryDetailDAO;
import com.webchat.pgc.repository.entity.mall.MallShop;
import com.webchat.pgc.repository.entity.sys.SysDataDictionary;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.jetbrains.annotations.NotNull;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;

import java.util.*;
import java.util.stream.Collectors;

/**
 * 数据字典服务
 *
 * @author SongRenShuo
 * @date 2025/06/25
 */
@Service
public class SysDataDictionaryService {

    @Autowired
    private ISysDataDictionaryDAO sysDataDictionaryDAO;
    @Autowired
    private ISysDataDictionaryDetailDAO sysDataDictionaryDetailDAO;
    @Autowired
    private RedisService redisService;
    @Autowired
    private ISysDataDictionaryCategoryDAO iSysDataDictionaryCategoryDAO;

    /**
     * 创建或者更新数据字典
     *
     * @param requestVO 请求 VO
     * @return {@link Long }
     */
    public Long save(SysDataDictionaryRequestVO requestVO) {
        parameterValidation(requestVO);

        Long id = requestVO.getId();
        if (id == null) {
            // 新增数据
            long countDistinctByCode = sysDataDictionaryDAO.countDistinctByCode(requestVO.getCode());
            Assert.isTrue(countDistinctByCode == 0, "字典编码已存在");
            long countDistinctByName = sysDataDictionaryDAO.countDistinctByName(requestVO.getName());
            Assert.isTrue(countDistinctByName == 0, "字典名称已存在");
        } else {
            // 修改数据
            long countDistinctByCode = sysDataDictionaryDAO.countDistinctByCodeAndIdNot(requestVO.getCode(), id);
            Assert.isTrue(countDistinctByCode == 0, "字典编码已存在");
            long countDistinctByName = sysDataDictionaryDAO.countDistinctByNameAndIdNot(requestVO.getName(), id);
            Assert.isTrue(countDistinctByName == 0, "字典名称已存在");
        }

        SysDataDictionary dataDictionary = sysDataDictionaryDAO.save(convert(requestVO));
        // 刷新缓存
        this.refreshCache(dataDictionary);
        // 清除详情缓存
        this.removeCacheDetail(dataDictionary.getId());
        return dataDictionary.getId();
    }

    /**
     * 删除数据数据字典
     *
     * @param dictionaryId 字典 ID
     * @param userId       用户 ID
     * @return boolean
     */
    @Transactional(rollbackFor = Exception.class)
    public boolean delete(Long dictionaryId, String userId) {
        Assert.notNull(dictionaryId, "字典ID不能为空");
        SysDataDictionary dataDictionary = sysDataDictionaryDAO.findById(dictionaryId).orElseThrow(() -> new BusinessException("字典信息不存在：" + dictionaryId));
        // 删除数据字典
        sysDataDictionaryDAO.deleteById(dictionaryId);
        // 删除数据字典详情
        sysDataDictionaryDetailDAO.deleteByDataDictionaryId(dictionaryId);
        // 清除缓存
        this.removeCache(dataDictionary.getCode());
        this.removeCacheDetail(dictionaryId);
        return true;
    }

    /**
     * 分页查询数据字典
     *
     * @param categoryId     分类 ID
     * @param code     编号
     * @param name     名称
     * @param pageNo   页码
     * @param pageSize 每页条数
     * @return {@link APIPageResponseBean }<{@link SysDataDictionaryResponseVO }>
     */
    public APIPageResponseBean<SysDataDictionaryResponseVO> page(Long categoryId, String code, String name, Integer pageNo, Integer pageSize) {
        Pageable pageable = PageRequest.of(pageNo - 1, pageSize, Sort.by(Sort.Direction.DESC, "id"));

        boolean notBlankCode = StringUtils.isNotBlank(code);
        boolean notBlankName = StringUtils.isNotBlank(name);

        Page<SysDataDictionary> dataDictionaryEntities = sysDataDictionaryDAO
                .findByCategoryIdAndCodeAndNameLike(categoryId, notBlankCode ? code : null,
                        notBlankName ? name : null, pageable);

        List<SysDataDictionaryResponseVO> vos = new ArrayList<>();
        long totalElements = 0L;
        if (dataDictionaryEntities != null && CollectionUtils.isNotEmpty(dataDictionaryEntities.getContent())) {
            totalElements = dataDictionaryEntities.getTotalElements();
            vos = dataDictionaryEntities.getContent().stream().map(this::convert).collect(Collectors.toList());
        }
        return APIPageResponseBean.success(pageNo, pageSize, totalElements, vos);
    }


    /**
     * 参数验证
     *
     * @param requestVO 请求 VO
     */
    private static void parameterValidation(SysDataDictionaryRequestVO requestVO) {
        Assert.hasText(requestVO.getCode(), "字典编码不能为空");
        Assert.hasText(requestVO.getName(), "字典名称不能为空");
    }

    /**
     * 获取Redis缓存Key
     *
     * @param dataDictionaryCode 数据字典 编码
     * @return {@link String }
     */
    private static String getKey(String dataDictionaryCode) {
        return RedisKeyEnum.SYS_DATA_DICTIONARY_BASE_CACHE.getKey(dataDictionaryCode);
    }

    /**
     * 获取缓存
     *
     * @param dataDictionaryCode 数据字典 编码
     * @return {@link SysDataDictionaryBaseVO }
     */
    public SysDataDictionaryBaseVO baseDetail(String dataDictionaryCode) {
        Assert.hasText(dataDictionaryCode, "字典编号不能为空");
        String key = getKey(dataDictionaryCode);
        String cache = redisService.get(key);
        if (StringUtils.isBlank(cache)) {
            // 刷新数据字典缓存
            return this.refreshCache(dataDictionaryCode);
        }
        return JsonUtil.fromJson(cache, SysDataDictionaryBaseVO.class);
    }

    /**
     * 刷新数据字典信息
     *
     * @param dataDictionaryCode 数据字典代码
     * @return {@link SysDataDictionaryBaseVO }
     */
    public SysDataDictionaryBaseVO refreshCache(String dataDictionaryCode) {

        SysDataDictionary dataDictionary = sysDataDictionaryDAO.findOneByCode(dataDictionaryCode);
        return this.refreshCache(dataDictionary);
    }
    /**
     * 刷新缓存
     *
     * @param dataDictionary 数据字典
     * @return {@link SysDataDictionaryBaseVO }
     */
    public SysDataDictionaryBaseVO refreshCache(SysDataDictionary dataDictionary) {
        if (dataDictionary == null) {
            return null;
        }
        String key = getKey(dataDictionary.getCode());
        SysDataDictionaryBaseVO dataDictionaryBaseVO = this.convert(dataDictionary);
        redisService.set(key, JsonUtil.toJsonString(dataDictionary),
                RedisKeyEnum.SYS_DATA_DICTIONARY_BASE_CACHE.getExpireTime());
        return dataDictionaryBaseVO;
    }


    /**
     * 删除缓存
     *
     * @param dataDictionaryCode 数据字典 编码
     */
    public void removeCache(String dataDictionaryCode) {
        String key = getKey(dataDictionaryCode);
        redisService.remove(key);
    }

    /**
     * 删除详情缓存
     *
     * @param dataDictionaryId 数据字典 ID
     */
    public void removeCacheDetail(Long dataDictionaryId) {
        String key = RedisKeyEnum.SYS_DATA_DICTIONARY_DETAIL_CACHE.getKey(dataDictionaryId.toString());
        redisService.remove(key);
    }

    /**
     * 转换
     *
     * @param requestVO 请求 VO
     * @return {@link SysDataDictionary }
     */
    private SysDataDictionary convert(SysDataDictionaryRequestVO requestVO) {

        String operator = requestVO.getOperator();
        Long id = requestVO.getId();
        Date now = new Date();
        SysDataDictionary dataDictionary;
        if (id != null) {
            dataDictionary = sysDataDictionaryDAO.findById(id).orElse(null);
            Assert.notNull(dataDictionary, "数据字典分类不存在");
        } else {
            dataDictionary = new SysDataDictionary();
            dataDictionary.setCreateBy(operator);
            dataDictionary.setCreateDate(now);
        }
        dataDictionary.setCode(requestVO.getCode());
        dataDictionary.setName(requestVO.getName());
        dataDictionary.setDescription(requestVO.getDescription());
        dataDictionary.setCategoryId(requestVO.getCategoryId());
        dataDictionary.setUpdateBy(operator);
        dataDictionary.setUpdateDate(now);
        return dataDictionary;
    }

    /**
     * 转换
     *
     * @return {@link SysDataDictionaryResponseVO }
     */
    private SysDataDictionaryResponseVO convert(SysDataDictionary dataDictionary) {
        if (dataDictionary == null) {
            return null;
        }
        SysDataDictionaryResponseVO dataDictionaryCategoryBaseVo = new SysDataDictionaryResponseVO();
        BeanUtils.copyProperties(dataDictionary, dataDictionaryCategoryBaseVo);
        Long categoryId = dataDictionaryCategoryBaseVo.getCategoryId();
        if (categoryId != null) {
            iSysDataDictionaryCategoryDAO.findById(categoryId).ifPresent(dataDictionaryCategory -> {
                dataDictionaryCategoryBaseVo.setCategoryName(dataDictionaryCategory.getName());
            });
        }
        return dataDictionaryCategoryBaseVo;
    }


}
